package com.sse.logica;

import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Clase que se encarga de gestionar las colas 
 * de eventos y de alarmas.
 * @author Paul
 *
 */
public class ManejadorColas implements IManejadorColas{
	
	private static final ManejadorColas instance = new ManejadorColas();
	
	private static final int QUEUE_TASK_THREADS = 30;
	
	public enum TipoColaEnum {
		EVENTOS,
		ALERTAS
	}
	
	/** Cola de alertas. */
	private ColaAlertasObservable<byte[]> colaAlertas;

	/** Cola de eventos */
	private ColaEventosObservable<byte[]> colaEventos;
	
	//JMANJARRES - CAmbio realizado para ejecutar el encolamiento asincrono de eventos.
	
	private ExecutorService queueTaskThreadPool = null;
		
	private ManejadorColas() {		
		colaAlertas = new ColaAlertasObservable<byte[]>();
		colaEventos = new ColaEventosObservable<byte[]>();
		
		queueTaskThreadPool = Executors.newFixedThreadPool(QUEUE_TASK_THREADS);
	}
	
	

	@Override
	public void encolarEventoAsincrono(byte[] data) {		
		QueueTask q = new QueueTask(TipoColaEnum.EVENTOS, data);
		this.queueTaskThreadPool.execute(q);		
	}
	
		
	
	
	public static ManejadorColas getInstance() {
		return instance;
	}	
	
	
	@Override
	public void suscribirProcesadorEventos(Observer procesador) {
		this.colaEventos.addObserver(procesador);
		
	}

	@Override
	public void suscribirProcesadorAlertas(Observer procesador) {
		this.colaAlertas.addObserver(procesador);
		
	}


	@Override
	public void encolarEvento(byte[] data) {
		this.colaEventos.encolar(data);	
	}


	@Override
	public void encolarAlerta(byte[] data) {
		this.colaAlertas.encolar(data);
	}


	@Override
	public synchronized void encolarAlertaConPrioridad(byte[] data) {
		this.colaAlertas.encolarConAltaPrioridad(data);
		
	}


	@Override
	public byte[] obtenerAlerta() {		
		return colaAlertas.obtener();
	}


	@Override
	public byte[] obtenerEvento() {
		return this.colaEventos.obtener();
	}

	
	public static void main(String[] args) {
		
		final IManejadorColas m = ManejadorColas.getInstance();
		
		byte[][] array = new byte[][] {
				{0,1,0,0},
				{1,2,0,0},
				{1,1,1,1},
				{1,0,0,1},
				{1,0,20,3},		
		};
	
		m.suscribirProcesadorAlertas(new Observer() {			
			@Override
			public void update(Observable o, Object arg) {				
				System.out.println("Alerta: "+m.obtenerAlerta());				
			}
		});
		
		m.suscribirProcesadorEventos(new Observer() {
			
			@Override
			public void update(Observable o, Object arg) {
				System.out.println("Evento: "+m.obtenerEvento());
				
			}
		});
		
		for (int i = 0; i < array.length; i++) {
			m.encolarAlerta(array[i]);
			m.encolarEvento(array[i]);
			m.encolarEvento(array[i]);
			
		}
				
		
	}
	
	private class QueueTask implements Runnable{

		private TipoColaEnum tipoColaEnum;
		private byte[] data;
		
	
		public QueueTask(TipoColaEnum tipoColaEnum, byte[] data) {
			this.tipoColaEnum = tipoColaEnum;
			this.data = data;
		}



		@Override
		public void run() {
//			System.out.println("Thread: "+Thread.currentThread()+" Encolado asincrono. ");
			switch (tipoColaEnum) {
			case ALERTAS:
				colaAlertas.encolar(data);
				break;
			case EVENTOS:
				colaEventos.encolar(data);				
				break;

			default:
				break;
			}				
			
		}
		
		
		
	}




}
